<?php
/**
 *
 *
 * @author Zeon <scplay@gmail.com>
 * @date 2018/6/26 14:45
 * @copyright PanxSoft Inc.
 */

namespace App\Services\Repositories\Pack;


use App\Http\Requests\Admin\Customer\Store\PackIndexRequest;
use App\Models\Customer\Asset;
use App\Models\Customer\PackAssetPivotProduct;
use App\Models\Panx\Product;
use App\Models\Store\Pack;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;

class PackRepository
{
    const DEFAULT_ORDER_BYS = [
        ['order_by' => 'created_at', 'sort' => 'desc'],
    ];

    /**
     * 从 PackAssetPivotProduct 中对应 Customer 缓存的列表中搜索对应 Pack / Asset ID 所关联的商品集合
     *
     * 使用 assets -> assetPivotProducts 再使用 pivot 表中的 pack_id 过滤
     * 在有 with 商品图片的情况下效率比这个高，因为这个多查了 3 次数据库
     *
     * @param int $customer_id
     * @param Pack $pack
     * @param Asset $asset
     *
     * @return Collection|Product[]
     */
    static public function filterCachedCustomerPackAssetRelationProducts(int $customer_id,
                                                                         Pack $pack,
                                                                         Asset $asset): Collection
    {
        return (new PackAssetPivotProduct)

            // filter from customer cached pivots
            ->getCustomerCache($customer_id)
            ->where('pack_id', $pack->id)
            ->where('asset_id', $asset->id)

            // some pivot's product id may error, cannot get right relation product
            // and we must filter invalidate product before map method,
            // because if one product is null, map would return support collection rather than eloquent collection
            ->filter(function (PackAssetPivotProduct $pivot) {
                return (bool) $pivot->product;
            })

            // transform pivot to it's relation product
            ->map(function (PackAssetPivotProduct $pivot) {
                return $pivot->product;
            })

            // convert to sequence index and keep type eloquent collection
            ->values();
    }

    /**
     * @param Pack $pack
     * @return mixed
     * @throws \App\Exceptions\ApiException
     */
    static public function deletePack(Pack $pack)
    {
        $deleted = Transaction::handle(function() use($pack){

            // 删除pack_pivot_asset表的数据
            $pack->assets()->detach();

            // 删除pack_asset_pivot_product表的数据
            (new PackAssetPivotProduct)->where('pack_id', $pack->id)->delete();

            // 共享pack 关联的 src_pack_id 重置成 0
            $pack->sharePacks()->update(['src_pack_id' => 0]);

            $deleted = $pack->delete();

            return $deleted;
        });

        return $deleted;
    }

    /**
     * @param Request|PackIndexRequest $request
     * @return Pack[]|LengthAwarePaginator
     */
    public function getPackPaginate(Request $request)
    {
        /** @var LengthAwarePaginator|Pack[] $packs */
        $packs = (new Pack)
            ->filterPackCategoryId($request->pack_category_id)
            ->orderBys($request->order_bys, self::DEFAULT_ORDER_BYS)
            ->filterIsDeleted($request->is_deleted)
            ->columnsKeywordsOrLike(['name'=>$request->name])
            ->latest('priority')
            ->with([
                'assets.assetPivotProducts.thumbImage'
            ])
            ->when( Guard::CustomerAdmin(),function (Builder $query){
                $query->where('customer_id', Guard::CustomerAdmin()->customer_id)
                    ->where('store_id', Pack::STORE_ID_CUSTOMER);
            })
            ->when( Guard::storeAdmin(), function (Builder $query) {
                $query->where('store_id', Guard::storeAdmin()->store_id);
            })
            ->paginate($request->per_page ?: 15);

        return $packs;
    }
}